package com.spzx.cart.service.impl;

import com.spzx.cart.domain.CartInfo;
import com.spzx.cart.service.CartService;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.domain.ProductSku;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private RemoteProductService remoteProductService;

    @Override
    public void addToCart(Long skuId, Integer num) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //根据情况判断是在购物车新增商品还是修改商品数量
        CartInfo cartInfo = (CartInfo)redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if(cartInfo != null){
            cartInfo.setSkuNum(cartInfo.getSkuNum() + num);
        }else{
            cartInfo = new CartInfo();
            R<ProductSku> productSkuR = remoteProductService.getProductSkuForCart(skuId, "inner");
            ProductSku productSku = productSkuR.getData();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setCartPrice(productSku.getSalePrice());
            cartInfo.setSkuPrice(productSku.getSalePrice());
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setThumbImg(productSku.getThumbImg());
            cartInfo.setSkuNum(num);
        }
        //将购物车数据存储到redis中
        redisTemplate.opsForHash().put(getCartKey(userId), skuId.toString(), cartInfo);
    }

    @Override
    public List<CartInfo> getCartList() {

        BoundHashOperations<String, String, CartInfo> hashOperation = redisTemplate.boundHashOps(getCartKey(SecurityContextHolder.getUserId()));

        List<CartInfo> cartList = hashOperation.values();
        if(cartList != null && !cartList.isEmpty()){
            List<Long> skuIdList = cartList.stream().map(CartInfo::getSkuId).toList();
            R<List<ProductSku>> skuPriceListR = remoteProductService.getSkuPriceList(skuIdList,"inner");
            List<ProductSku> skuPriceList = skuPriceListR.getData();
            Map<Long, BigDecimal> skuPriceMap = skuPriceList.stream().collect(Collectors.toMap(ProductSku::getId, ProductSku::getSalePrice));
            for (CartInfo cartInfo : cartList) {
                cartInfo.setSkuPrice(skuPriceMap.get(cartInfo.getSkuId()));
            }
        }
        return cartList;
    }

    @Override
    public void deleteCartBySkuId(Long skuId) {
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(getCartKey(SecurityContextHolder.getUserId()));
        hashOperations.delete(skuId.toString());
    }

    @Override
    public void alertCheckCart(Long skuId, Integer isChecked) {
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(getCartKey(SecurityContextHolder.getUserId()));
        CartInfo cartInfo = hashOperations.get(skuId.toString());
        if(cartInfo != null){
            cartInfo.setIsChecked(isChecked);
            hashOperations.put(skuId.toString(), cartInfo);
        }
    }

    @Override
    public void alertAllCheckCart(Integer isChecked) {
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(getCartKey(SecurityContextHolder.getUserId()));
        List<CartInfo> cartInfoList = hashOperations.values();
        Map<String, CartInfo> cartInfoMap = cartInfoList.stream().map(new Function<CartInfo, CartInfo>() {
            @Override
            public CartInfo apply(CartInfo cartInfo) {
                cartInfo.setIsChecked(isChecked);
                return cartInfo;
            }
        }).collect(Collectors.toMap(new Function<CartInfo, String>() {
            @Override
            public String apply(CartInfo cartInfo) {
                return cartInfo.getSkuId() + "";
            }
        }, new Function<CartInfo, CartInfo>() {
            @Override
            public CartInfo apply(CartInfo cartInfo) {
                return cartInfo;
            }
        }));
        hashOperations.putAll(cartInfoMap);
    }

    @Override
    public void clearCart() {
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(getCartKey(SecurityContextHolder.getUserId()));
        List<CartInfo> cartInfoList = hashOperations.values();
        if(cartInfoList != null){
            List<String> skuIdList = cartInfoList.stream().map(cartInfo -> cartInfo.getSkuId() + "").toList();
            skuIdList.forEach(skuId -> hashOperations.delete(skuId));
        }
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        List<CartInfo> list = new ArrayList<>();
        if(!cartInfoList.isEmpty()){
            list = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).toList();
        }
        return list;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOperations.values();
        if(cartInfoList !=null && !cartInfoList.isEmpty()){
            List<CartInfo> cartInfoListChecked = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).toList();
            List<Long> skuIdList = cartInfoListChecked.stream().map(CartInfo::getSkuId).toList();
            R<List<ProductSku>> skuPriceListR = remoteProductService.getSkuPriceList(skuIdList,"inner");
            List<ProductSku> skuPriceList = skuPriceListR.getData();
            Map<Long, BigDecimal> skuPriceMap = skuPriceList.stream().collect(Collectors.toMap(ProductSku::getId, ProductSku::getSalePrice));
            for (CartInfo cartInfo : cartInfoListChecked) {
                cartInfo.setSkuPrice(skuPriceMap.get(cartInfo.getSkuId()));
            }
            Map<String, CartInfo> collect = cartInfoListChecked.stream().collect(Collectors.toMap(new Function<CartInfo, String>() {
                @Override
                public String apply(CartInfo cartInfo) {
                    return cartInfo.getSkuId() + "";
                }
            }, new Function<CartInfo, CartInfo>() {
                @Override
                public CartInfo apply(CartInfo cartInfo) {
                    return cartInfo;
                }
            }));
            hashOperations.putAll(collect);
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOperations.values();
        if(cartInfoList !=null && !cartInfoList.isEmpty()){
            List<CartInfo> cartInfoListChecked = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked() == 1).toList();
            List<String> list = cartInfoListChecked.stream().map(cartInfo -> cartInfo.getSkuId() + "").toList();
            list.forEach(skuId -> hashOperations.delete(skuId));
        }
        return true;
    }

    public String getCartKey(Long userId){
        return "user:cart:" + userId;
    }
}
